﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Temp.Controller;
using Temp.Model;
using Temp.Planner2;

namespace Temp.NLG
{
    class Describer
    {
        private List<string> sentenceList;
        private StringBuilder paragraph;
        private List<ItemController> listAttributes;

        private MessageTempController mtc;
        private NPCDialogueController ndc;
        private ObjectController oc;
        private OntologyController ontC;
        private ItemController ic;
        private CharacterController cc;
        private LexiconController lc;

        private StoryPlanner storyPlanner;

        public string NPCTYPE = "NPC";
        public string ITEMTYPE = "ITEM";
        public string PEERTYPE = "PEER";

        public Describer(StoryPlanner storyPlanner)
        {
            paragraph = new StringBuilder();
            mtc = new MessageTempController();
            oc = new ObjectController();
            ic = new ItemController();
            lc = new LexiconController();
            cc = new CharacterController();
            ndc = new NPCDialogueController();
            ontC = new OntologyController();
            this.storyPlanner = storyPlanner;
            sentenceList = new List<string>();
        }

        public List<Conversation> getItemDescription(string name, string type)
        {
            List<Conversation> listConversation = new List<Conversation>();
            sentenceList = new List<string>();
            List<string> speakerList = new List<string>();
            paragraph.Clear();

            if (sentenceList != null)
            {
                sentenceList.Clear();
                System.Diagnostics.Debug.WriteLine("sentence list cleared " + sentenceList.Count);
            }

            if (listAttributes != null)
            {
                listAttributes.Clear();
                System.Diagnostics.Debug.WriteLine("attrib list cleared " + listAttributes.Count);
            }


            if (type == ITEMTYPE)
                sentenceList = mtc.getMessageTemplateForItems();
            else if (type == NPCTYPE)
            {

                sentenceList = ndc.getDialogue(storyPlanner.currentStoryNode.name, name);
                speakerList = ndc.getSpeakers(storyPlanner.currentStoryNode.name, name);
                System.Diagnostics.Debug.WriteLine("NODE NAME:" + storyPlanner.currentStoryNode.name + "size sentence list:" + sentenceList.Count);
            }
            System.Diagnostics.Debug.WriteLine("SENTENCE COUNT" + sentenceList.Count + "\n");
            int ctr = 0; 
            foreach (string s in sentenceList)
            {   

                System.Diagnostics.Debug.WriteLine("SENTENCE" + s + "\n");
                Conversation c = fillUpSentence(s, name, type);
                if (type == ITEMTYPE) {
                    c.name = "Alex";
                }
                else if (type == NPCTYPE) {
                    System.Diagnostics.Debug.WriteLine("speaker name:" + speakerList[ctr]);
                    c.name = speakerList[ctr];
                }
                listConversation.Add(c);
                ctr++;
            }

            if (type == ITEMTYPE)
                return reindexConversationList(listConversation);
            else if (type == NPCTYPE)
                return listConversation;

            return null;
        }

        public List<Conversation> getItemDescription2(string name, string sentence)
        {
            List<Conversation> listConversation = new List<Conversation>();
            sentenceList = new List<string>();
           
            List<string> speakerList = new List<string>();
            paragraph.Clear();

            if (sentenceList != null)
            {
                sentenceList.Clear();
                System.Diagnostics.Debug.WriteLine("sentence list cleared " + sentenceList.Count);
            }

            if (listAttributes != null)
            {
                listAttributes.Clear();
                System.Diagnostics.Debug.WriteLine("attrib list cleared " + listAttributes.Count);
            }


            sentenceList.Add(sentence);
            System.Diagnostics.Debug.WriteLine("SENTENCE COUNT" + sentenceList.Count + "\n");
            int ctr = 0;
            foreach (string s in sentenceList)
            {

                System.Diagnostics.Debug.WriteLine("SENTENCE" + s + "\n");
                Conversation c = fillUpSentence(s, name, ITEMTYPE);
                
                    c.name = "Alex";
                
                listConversation.Add(c);
                ctr++;
            }

            return reindexConversationList(listConversation);
           
            
        }


        public Conversation fillUpPeerMessage(string message, List<Item> listInventory) {
            Conversation c = new Conversation("Alex", "", 'P');
            string listItems = fillUpSentence(message, "", PEERTYPE).dialogue;
            foreach (Item i in listInventory) {
                listItems = listItems.Replace(", " + i.name.ToLower(), "");
                listItems = listItems.Replace(i.name.ToLower() + ",", "");
            }
            c.dialogue = listItems;
            return c; 
        }

        private List<Conversation> reindexConversationList(List<Conversation> listConversation)
        {
            List<Conversation> tempConversationList = new List<Conversation>();
            tempConversationList.Add(listConversation[0].clone());
            for (int i = 1; i < listConversation.Count; i++)
            {
                if (listConversation[i].optionList.Count == 0)
                {
                    tempConversationList[0].dialogue += " " + listConversation[i].dialogue;
                }
                else
                {
                    System.Diagnostics.Debug.WriteLine("trigger name : " + listConversation[i].nameOfTriggerer + "trigger type: " + listConversation[i].typeOfTriggerer);
                    tempConversationList.Add(listConversation[i].clone());
                    System.Diagnostics.Debug.WriteLine("trigger name : " + tempConversationList.Last().nameOfTriggerer + "trigger type: " + tempConversationList.Last().typeOfTriggerer);

                }
            }
            return tempConversationList;
        }

        private Conversation fillUpSentence(string s, string name, string type)
        {
            Conversation c = new Conversation("Alex", "", 'T');
            MatchCollection matchC;
            String pattern = "<(_|[a-z]|[A-Z]|[0-9]| )+>";

            matchC = Regex.Matches(s, pattern);

            foreach (Match m in matchC)
            {
                System.Diagnostics.Debug.WriteLine("MATCH VALUE:" + m.Value);
                s = s.Replace(m.Value.ToString(), getRelationValue(m.Value, c, name, type));
            }
            c.dialogue = s;
            return c;
        }

        private string getRelationValue(string matchVal, Conversation c, string name, string type)
        {
            List<Ontology> listItemOnt = new List<Ontology>();
            List<Ontology> listCharacterOnt = new List<Ontology>();
            bool optionTypeRelationFound = false;
            string temp = matchVal;
            temp = temp.Replace("<", "");
            temp = temp.Replace(">", "");
            String l = lc.getSynonym(temp, "Lexicon_Relation");
            if (type == ITEMTYPE)
            {
                System.Diagnostics.Debug.WriteLine("HERE HERE ITEM ");
                listItemOnt = ic.getAttributeValue(temp, name);
               
            }

            else if (type == PEERTYPE && temp.Contains("ITEM")) {
                string[] info = temp.Split('_');
                string rel = info[1].ToLower();
                string concept = info[2].ToLower();
                listItemOnt = ic.getNeededItems(rel,concept);
            }


            else if (type == NPCTYPE)
            {   if(checkRelation(temp, "Character_ont")){
                   optionTypeRelationFound = true;
                }
                listCharacterOnt = cc.getAttributeValues(temp, name);
            }
            //System.Diagnostics.Debug.WriteLine("list item ont count" + listItemOnt.Count + " name " + itemName);
            if (optionTypeRelationFound || listItemOnt.Count >= 2)
            {
                System.Diagnostics.Debug.WriteLine("list item count > 2");

                c.nameOfTriggerer = name;

                if (type == ITEMTYPE)
                {
                    c.typeOfTriggerer = "Item";
                    foreach (Ontology io in listItemOnt)
                    {
                        c.optionList.Add(io.concept2);
                    }
                   
                }
                else if (type == PEERTYPE) {
                    string items = "";
                    int counter = 0; 
                    foreach (Ontology o in listItemOnt) {
                        if (counter == listItemOnt.Count-1) {
                            items += o.concept1.ToLower();
                        }
                        else
                            items += o.concept1.ToLower() +", ";
                        counter++;
                    }
                    return items;
                }
                else if (type == NPCTYPE)
                {
                    optionTypeRelationFound = false;
                    List<Ontology> storyNodeList, optionList; 
                    c.typeOfTriggerer = "NPC";
                    
                    foreach (Ontology co in listCharacterOnt)
                    {
                        storyNodeList = cc.getStoryNodeOptionUsed(co.concept2);

                        for (int i = 0; i < storyNodeList.Count; i++) {
                            if (storyNodeList[i].concept2 == storyPlanner.currentStoryNode.name || storyNodeList[i].concept2 == "DEFAULT") {
                                optionList = cc.getValues(co.concept2);
                                foreach (Ontology option in optionList) {
                                    c.optionList.Add(option.concept2);
                                }
                                i = storyNodeList.Count; 
                            }
                        }
                            
                    }
                }

                return "";
            }

            else if (listItemOnt.Count == 1)
            {
                System.Diagnostics.Debug.WriteLine("list item count < 1 value:" + listItemOnt[0].concept2);

                if (l != "")
                    return l + " " + listItemOnt[0].concept2;
                else
                    return listItemOnt[0].concept2;

            }

            return name;
        }

        private bool checkRelation(string relation, string table) {
            Ontology o = new Ontology();
            o = ontC.getRelationsUse(table, relation);
            System.Diagnostics.Debug.WriteLine(o.concept2);
            if (o == null)
            {
                System.Diagnostics.Debug.WriteLine("OPT PROVIDE not FOUND");
                return false;
            }
            else if (o.concept2 == "OPTION_PROVIDER")
            {
                System.Diagnostics.Debug.WriteLine("OPT PROVIDE FOUND");
                return true;
            }
            return false;
        }

    }
}
